// 微信工具类

package common

import (
	"api/common/logger"
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/http"
	"time"
)

type Item struct {
	Field string `json:"field"`
	Value string `json:"value"`
}

// 获取微信小程序全局唯一后台接口调用凭据
// 返回值: (wx_access_token, errMsg)
func GetAccessToken() (string, string) {
	token := ""
	err := RedisClient.Get("wx_access_token").Scan(&token)
	if err == nil {
		return token, ""
	}

	url := "https://api.weixin.qq.com/cgi-bin/token" +
		"?grant_type=client_credential" +
		"&appid=" + Config.WX.AppID +
		"&secret=" + Config.WX.AppSecret
	req, err := http.NewRequest("get", url, nil)
	if err != nil {
		logger.Error("获取微信访问令牌发生错误 http.NewRequest", err)
		return "", "获取微信访问令牌发生错误" + err.Error()
	}

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logger.Error("获取微信访问令牌发生错误 client.Do", err)
		return "", "获取微信访问令牌发生错误" + err.Error()
	}

	if resp.StatusCode != 200 {
		return "", "获取微信访问令牌发生错误 " + ToStr(resp.StatusCode)
	}

	bodyByte, err := ioutil.ReadAll(resp.Body)
	_ = resp.Body.Close()
	if err != nil {
		logger.Error("获取微信访问令牌发生错误 ioutil.ReadAll", err)
		return "", "获取微信访问令牌发生错误" + err.Error()
	}

	inputJson := map[string]interface{}{}
	err = json.Unmarshal(bodyByte, &inputJson)
	if err != nil {
		logger.Error("获取微信访问令牌发生错误 json.Unmarshal", err)
		return "", "获取微信访问令牌发生错误" + err.Error()
	}

	errMsg := inputJson["errmsg"]
	if errMsg != nil {
		return "", "获取微信访问令牌发生错误" + ToStr(errMsg)
	}

	access_token := inputJson["access_token"]
	expires_in := inputJson["expires_in"]
	token = ToStr(access_token)
	expires := time.Duration(expires_in.(float64))
	RedisClient.Set("wx_access_token", token, time.Second*expires)

	return token, ""
}

// 发送订阅消息
// {"touser":"openid", "template_id":"模板id", "data":{ "thing1": { "value": "" }, "thing2": { "value": "" } }}
// 参数: toUser, templateId, sendData
// 返回值: errMsg
func SendMsg(toUser string, templateId string, sendData []Item) string {
	token, errMsg := GetAccessToken()
	if errMsg != "" {
		return errMsg
	}

	url := "https://api.weixin.qq.com/cgi-bin/message/subscribe/send" +
		"?access_token=" + token
	params := map[string]interface{}{}
	params["touser"] = toUser
	params["template_id"] = templateId
	data := map[string]interface{}{}

	// 核心代码
	for i := 0; i < len(sendData); i += 1 {
		item := sendData[i]
		obj := map[string]interface{}{}
		obj["value"] = item.Value
		data[item.Field] = obj
	}

	params["data"] = data
	jsonStr, _ := json.Marshal(params)
	para := bytes.NewBuffer(jsonStr)
	req, err := http.NewRequest("post", url, para)
	if err != nil {
		logger.Error("发送订阅消息发生错误 http.NewRequest", err)
		return "发送订阅消息发生错误" + err.Error()
	}

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logger.Error("发送订阅消息发生错误 client.Do", err)
		return "发送订阅消息发生错误" + err.Error()
	}

	if resp.StatusCode != 200 {
		return "发送订阅消息发生错误 " + ToStr(resp.StatusCode)
	}

	bodyByte, err := ioutil.ReadAll(resp.Body)
	_ = resp.Body.Close()
	if err != nil {
		logger.Error("发送订阅消息发生错误 ioutil.ReadAll", err)
		return "发送订阅消息发生错误" + err.Error()
	}

	inputJson := map[string]interface{}{}
	err = json.Unmarshal(bodyByte, &inputJson)
	if err != nil {
		logger.Error("发送订阅消息发生错误 json.Unmarshal", err)
		return "发送订阅消息发生错误" + err.Error()
	}

	errmsg := inputJson["errmsg"]
	if errmsg != nil {
		errStr := ToStr(errmsg)
		if errStr != "ok" {
			return "发送订阅消息发生错误" + errStr
		}
	}

	return ""
}

// 发送客服消息
// {"touser":"openid", "msgtype":"link", "link":{ "title": "", "description": "", "url": "", "thumb_url": "" }}
// 参数: toUser, msgType, sendData
// 返回值: errMsg
func SendChat(toUser string, msgType string, sendData map[string]interface{}) string {
	token, errMsg := GetAccessToken()
	if errMsg != "" {
		return errMsg
	}

	url := "https://api.weixin.qq.com/cgi-bin/message/custom/send" +
		"?access_token=" + token
	params := map[string]interface{}{}
	params["touser"] = toUser
	params["msgtype"] = msgType
	params[msgType] = sendData

	jsonStr, _ := json.Marshal(params)
	para := bytes.NewBuffer(jsonStr)
	req, err := http.NewRequest("post", url, para)
	if err != nil {
		logger.Error("发送客服消息发生错误 http.NewRequest", err)
		return "发送客服消息发生错误" + err.Error()
	}

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logger.Error("发送客服消息发生错误 client.Do", err)
		return "发送客服消息发生错误" + err.Error()
	}

	if resp.StatusCode != 200 {
		return "发送客服消息发生错误 " + ToStr(resp.StatusCode)
	}

	bodyByte, err := ioutil.ReadAll(resp.Body)
	_ = resp.Body.Close()
	if err != nil {
		logger.Error("发送客服消息发生错误 ioutil.ReadAll", err)
		return "发送客服消息发生错误" + err.Error()
	}

	inputJson := map[string]interface{}{}
	err = json.Unmarshal(bodyByte, &inputJson)
	if err != nil {
		logger.Error("发送客服消息发生错误 json.Unmarshal", err)
		return "发送客服消息发生错误" + err.Error()
	}

	errmsg := inputJson["errmsg"]
	if errmsg != nil {
		errStr := ToStr(errmsg)
		if errStr != "ok" {
			return "发送客服消息发生错误" + errStr
		}
	}

	return "success"
}
